﻿/// <reference path="Controls/BaseComplexControl.js" />
/// <reference path="../General/SizePos.js" />

var $Menu = TA.Turbo.Controls.Menu = function Menu(clientId)
{
	this.BaseComplexControl(clientId);
}
$Menu.Inherit(TA.Turbo.Controls.BaseComplexControl);

var _____a;
if (_____a)
{
	$Menu.prototype = new TA.Turbo.Controls.BaseComplexControl();
	$Menu.prototype.BaseComplexControl = new TA.Turbo.Controls.BaseComplexControl();
}




$PropertyDefinition.Define($Menu, "HideTimeout", "HT", 0);
$PropertyDefinition.Define($Menu, "DropDownTrigger", "DT", DropDownTrigger.Hover);

$Menu.DefineEvent(new $ClientEvent("ItemClick"));



$Menu.prototype._mouseOutTimeoutId = null;
$Menu.prototype._mouseDownItem = null;



$Menu.prototype.Init = function Init()
{
	this.BaseComplexControl.Init.call(this);

	document.AddEvent("mousedown", this._document_MouseDown, this);
	document.AddEvent("mouseup", this._document_MouseUp, this);
	this.get_Control().AddEvent("mousedown", this._control_MouseDown, this);
	this._ProcessMenu(this.get_Control());
	//	this.get_Control().AddEvent("mouseover", this._control_MouseOver, this);
	//	this.get_Control().AddEvent("mouseout", this._control_MouseOut, this);
}
$Menu.prototype.HideAll = function HideAll()
{
	var items = this._GetItems(this.get_Control());
	for (var i = 0; i < items.length; ++i)
		this._HideRecursive(items[i]);
}











$Menu.prototype._GetItems = function _GetItems(menu)
{
	if (menu._items === undefined)
		menu._items = menu.FindChildren("LI");
	return menu._items;
}
$Menu.prototype._GetAnchor = function _GetAnchor(item)
{
	if (item._anchor == null)
	{
		item._anchor = item.FindFirstChild("A");
	}
	return item._anchor;
}
$Menu.prototype._GetDropDown = function _GetDropDown(item)
{
	if (item._dropdown === undefined)
		item._dropdown = item.FindFirstChild("UL");
	return item._dropdown;
}


$Menu.prototype._GetDropDownTrigger = function _GetDropDownTrigger(item)
{
	if (item.getAttribute("t") != null)
		return parseInt(item.getAttribute("t"));
	return this.get_DropDownTrigger();
}
$Menu.prototype._ProcessMenu = function _ProcessMenu(menu)
{
	var items = this._GetItems(menu);
	for (var i = 0; i < items.length; ++i)
	{
		var item = items[i];

		item.AddEvent("mouseenter", this._item_MouseEnter, this);
		item.AddEvent("mouseleave", this._item_MouseLeave, this);

		var anchor = this._GetAnchor(item);
		anchor.AddEvent("click", this._item_anchor_Click, this);

		if (this._GetDropDownTrigger(item) == DropDownTrigger.Click)
		{
			item.AddEvent("mousedown", this._item_MouseDown, this);
			item.AddEvent("mouseup", this._item_MouseUp, this);
		}


		var dd = this._GetDropDown(item);
		if (dd != null)
		{
			this._ProcessMenu(dd);
		}
	}
}








$Menu.prototype._EnsurePosition_Horizontal = function _EnsurePosition_Horizontal(dd, loc, size)
{
	if (loc.x + size.w > window.get_Size().w)
	{ // dropdown is outside the window on the right
		if (dd.style["left"] == "100%")
		{ // dropdown is on the right of the containing item
			if (dd.parentNode.get_Location().x - size.w >= 0)
			{ // it would fit on the left
				dd.style["left"] = "";
				dd.style["right"] = "100%";
			}
		}
		else
		{ // dropdown is above or below
			dd.style["left"] = (window.get_Size().w - size.w - dd.parentNode.get_Location().x) + "px";
		}
	}

	if (loc.x < 0)
	{// dropdown is outside the window on the left
		if (dd.style["right"] == "0%")
		{ // dropdown is on the left of the containing item
			if (dd.parentNode.get_Location().x + dd.parentNode.offsetWidth + size.w <= window.get_Size().w)
			{ // it would fit on the right
				dd.style["right"] = "";
				dd.style["left"] = "100%";
			}
		}
		else
		{ // dropdown is above or below
			dd.style["left"] = "0px";
		}
	}
}
$Menu.prototype._EnsurePosition_Vertical = function _EnsurePosition_Vertical(dd, loc, size)
{
	if (loc.y + size.h > window.get_Size().h)
	{ // dropdown is outside the window in the bottom
		if (dd.style["top"] == "100%")
		{// dropdown is below the containing item
			if (dd.parentNode.get_Location().y - size.h > 0)
			{ // it would fit above
				dd.style["top"] = "";
				dd.style["bottom"] = "100%";
			}
		}
		else
		{ // dropdown is on the left or right
			dd.style["top"] = (window.get_Size().h - size.h - dd.parentNode.get_Location().y) + "px";
		}
	}

	if (loc.y < 0)
	{ // dropdown is outside the window on the top
		if (dd.style["bottom"] == "0%")
		{// dropdown is above the containing item
			if (loc.y + size.h < window.get_Size().h)
			{ // it would fit below
				dd.style["bottom"] = "";
				dd.style["top"] = "100%";
			}
		}
		else
		{ // dropdown is on the left or right
			dd.style["bottom"] = (dd.parentNode.get_Location().y - size.h) + "px";
		}
	}
}
$Menu.prototype._EnsurePosition = function _EnsurePosition(dd)
{
	var items = this._GetItems(dd);
	var size = new Size();
	for (var i = 0; i < items.length; ++i)
	{
		if (dd.HasClass("turbo_menu_mhor"))
		{
			size.w += items[i].offsetWidth;

			if (items[i].offsetHeight > size.h)
				size.h = items[i].offsetHeight;
		}
		else
		{
			if (items[i].offsetWidth > size.w)
				size.w = items[i].offsetWidth;

			size.h += items[i].offsetHeight;
		}
	}
	var loc = dd.get_Location();

	this._EnsurePosition_Horizontal(dd, loc, size);
	this._EnsurePosition_Vertical(dd, loc, size);
}

$Menu.prototype._Show = function _Show(item)
{
	item.RemoveClass("n");
	item.AddClass("a");

	var dd = this._GetDropDown(item);

	if (dd != null)
	{
		dd.style["display"] = "block";

		setTimeout(this._EnsurePosition.bind(this, dd), 10);
	}
}
$Menu.prototype._Hide = function _Hide(item)
{
	item.RemoveClass("a");
	item.AddClass("n");

	var dd = this._GetDropDown(item);
	if (dd != null)
	{
		dd.style["display"] = "none";
	}
}
$Menu.prototype._HideRecursive = function _HideRecursive(item)
{
	var dd = this._GetDropDown(item);
	if (dd != null)
	{
		var children = this._GetItems(dd);
		for (var iChild = 0; iChild < children.length; ++iChild)
		{
			this._HideRecursive(children[iChild]);
		}
	}


	this._Hide(item);
}

$Menu.prototype._ActivateItem = function _ActivateItem(item)
{
	if (this._mouseOutTimeoutId != null)
	{
		clearTimeout(this._mouseOutTimeoutId);
		this._mouseOutTimeoutId = null;
	}

	var parent = item.parentNode;
	var siblings = this._GetItems(parent);
	for (var i = 0; i < siblings.length; ++i)
	{
		this._HideRecursive(siblings[i]);
	}

	this._Show(item);
}
$Menu.prototype._TriggerItem = function _TriggerItem(item)
{
	var a = item.FindFirstChild("A");
	//	if (!String.IsNullOrEmpty(a.getAttribute("onclick")))
	//		eval(a.getAttribute("onclick").replace("return false;", ""));
	var arg = a.getAttribute("Arg");
	if (!String.IsNullOrEmpty(arg))
	{
		this.RaiseEvent("ItemClick", { Item: item, Argument: arg });

		var client = a.getAttribute("Client");
		eval(client);

		var psId = a.getAttribute("PS");
		if (!String.IsNullOrEmpty(psId))
			$DoPostBack(this.get_Control(), "Click", arg, psId, null);
	}
	else if (!String.IsNullOrEmpty(a.href) && !String.Equals(a.href, location.href, StringComparison.IgnoreCase))
		location.href = a.href;

	this.HideAll();
}







$Menu.prototype._document_MouseDown = function _document_MouseDown()
{
	this.HideAll();
}
$Menu.prototype._document_MouseUp = function _document_MouseUp()
{
	this._mouseDownItem = null;
	this.get_Control().set_SelectionEnabled(true);
}
$Menu.prototype._control_MouseDown = function _control_MouseDown(e)
{
	Events.Stop(e);
}




$Menu.prototype._item_anchor_Click = function _item_anchor_Click(e)
{
	var anchor = Events.GetSender(e);
	var item = anchor.parentNode;
	this._TriggerItem(item);
	Events.Cancel(e);
	Events.Stop(e);
}




$Menu.prototype._item_MouseEnter = function _item_MouseEnter(e)
{
	var item = Events.GetSender(e);

	switch (this._GetDropDownTrigger(item))
	{
		case DropDownTrigger.Hover: // just need to hover
			this._ActivateItem(item); // show
			break;
		case DropDownTrigger.Click: // need to click
			if (this._mouseDownItem != null) // already pushed mouse button elsewhere and dragged onto this one
				this._ActivateItem(item); // then show
			break;
	}
}
$Menu.prototype._item_MouseDown = function _item_MouseDown(e)
{
	var item = Events.GetSender(e);
	this._ActivateItem(item); // in any case, show
	Events.Stop(e);

	this._mouseDownItem = item; // for items that need to be clicked to be shown, this will indicate that mouse button was already pushed
	this.get_Control().set_SelectionEnabled(false);
}
$Menu.prototype._item_MouseUp = function _item_MouseUp(e)
{
	var item = Events.GetSender(e);
//	if (this._mouseDownItem != item)
	{
		if (this._GetDropDown(item) == null)
		{
			this._TriggerItem(item);
		}
	}
	this._mouseDownItem = null;
	Events.Stop(e);
	this.get_Control().set_SelectionEnabled(true);
}











$Menu.prototype._item_MouseLeave_Delayed = function _item_MouseLeave_Delayed(item)
{
	this._Hide(item);

	this._mouseOutTimeoutId = null;
	this._mouseOutElement = null;
}
$Menu.prototype._item_MouseLeave = function _item_MouseLeave(e)
{
	var item = Events.GetSender(e);
	if (this._GetDropDownTrigger(item) == DropDownTrigger.Hover)
		this._mouseOutTimeoutId = setTimeout(this._item_MouseLeave_Delayed.bind(this, item), this.get_HideTimeout());
}


